import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_app/Util/FileUtils.dart';
import 'package:flutter_yfree/YFree.dart';
import 'package:record/record.dart';

enum _ChatRecordType { Idle, Recording, Cancel }

class ChatRecordButton extends StatefulWidget {
  const ChatRecordButton({
    required this.onRecordFinish,
    this.maxSecond = 60,
    Key? key,
  }) : super(key: key);

  final Function(String path, int second) onRecordFinish;
  final int maxSecond;

  @override
  _ChatRecordButtonState createState() => _ChatRecordButtonState();
}

class _ChatRecordButtonState extends State<ChatRecordButton> {
  _ChatRecordType chatRecordType = _ChatRecordType.Idle;
  double recordY = 0;
  final record = Record();
  String? recordPath;
  OverlayEntry? overlay;
  StateSetter? setState_layer;
  int voiceLevel = 1;
  StreamSubscription? streamSubscription;
  Timer? timer;
  int second = 0;

  @override
  void dispose() {
    removeRecordView();
    super.dispose();
  }

  void addRecordView() {
    overlay = OverlayEntry(
      builder: (context) {
        return StatefulBuilder(
          builder: (context, setState) {
            setState_layer = setState;
            return Scaffold(
              backgroundColor: Colors.transparent,
              body: Center(
                child: Container(
                  width: 150,
                  height: 150,
                  padding: EdgeInsets.all(10),
                  decoration: BoxDecoration(color: Colors.black.withAlpha(100), borderRadius: BorderRadius.circular(10)),
                  alignment: Alignment.center,
                  child: Column(
                    children: [
                      Image.asset(
                        chatRecordType == _ChatRecordType.Recording ? "images/record/voice_volume_$voiceLevel.png" : "images/record/cancel_voice.png",
                        width: 100,
                        height: 100,
                      ),
                      Text("${widget.maxSecond - second}s", style: TextStyle(color: Colors.white)),
                    ],
                  ),
                ),
              ),
            );
          },
        );
      },
    );
    Overlay.of(context).insert(overlay!);
  }

  void removeRecordView() {
    setState_layer = null;
    try {
      overlay?.remove();
    } catch (e) {}
    overlay = null;
    try {
      streamSubscription?.cancel();
    } catch (e) {}
    streamSubscription = null;
    voiceLevel = 1;
    timer?.cancel();
    timer = null;
    second = 0;
  }

  Widget view_record() {
    switch (chatRecordType) {
      case _ChatRecordType.Idle:
        return Container(
          margin: EdgeInsets.only(top: 5, bottom: 5),
          decoration: BoxDecoration(color: YConfig.themeColor.withAlpha(180), borderRadius: BorderRadius.circular(5)),
          alignment: Alignment.center,
          constraints: BoxConstraints(minHeight: 30),
          child: Text("按住说话", style: TextStyle(fontSize: 14, color: Colors.white)),
        );
      case _ChatRecordType.Recording:
        return Container(
          margin: EdgeInsets.only(top: 5, bottom: 5),
          decoration: BoxDecoration(color: YConfig.themeColor.withAlpha(50), borderRadius: BorderRadius.circular(5)),
          alignment: Alignment.center,
          constraints: BoxConstraints(minHeight: 30),
          child: Text("松手发送，向上取消", style: TextStyle(fontSize: 14, color: Colors.grey)),
        );
      case _ChatRecordType.Cancel:
        return Container(
          margin: EdgeInsets.only(top: 5, bottom: 5),
          decoration: BoxDecoration(color: Colors.grey.shade300, borderRadius: BorderRadius.circular(5)),
          alignment: Alignment.center,
          constraints: BoxConstraints(minHeight: 30),
          child: Text("松手取消，向下发送", style: TextStyle(fontSize: 14, color: Colors.grey)),
        );
    }
  }

  void refresh() {
    try {
      setState(() {});
      setState_layer?.call(() {});
    } catch (e) {}
  }

  Future<void> start(DragDownDetails details) async {
    recordY = details.globalPosition.dy;
    chatRecordType = _ChatRecordType.Recording;
    refresh();
    addRecordView();
    if (!(await record.hasPermission())) {
      yToast("请授予录音权限");
      return;
    }
    recordPath = "${await FileUtils.getDir(FileDir.chat_record)}/${DateTime.now().microsecondsSinceEpoch}.m4a";
    record.start(path: recordPath, encoder: AudioEncoder.aacLc);
    streamSubscription = record.onAmplitudeChanged(Duration(milliseconds: 100)).listen((event) {
      double current = 50 - -event.current;
      try {
        voiceLevel = current ~/ 7;
        if (voiceLevel < 1) voiceLevel = 1;
        if (voiceLevel > 7) voiceLevel = 7;
      } catch (e) {
        voiceLevel = 1;
      }
      refresh();
    });
    timer = Timer.periodic(Duration(seconds: 1), (timer) {
      second++;
      if (second >= widget.maxSecond) finish();
    });
  }

  void update(DragUpdateDetails details) {
    if (details.globalPosition.dy < yScreenSize().height - yScreenSize().height / 5) {
      chatRecordType = _ChatRecordType.Cancel;
    } else {
      chatRecordType = _ChatRecordType.Recording;
    }
    refresh();
  }

  Future<void> finish() async {
    await record.stop();
    if (chatRecordType == _ChatRecordType.Recording) {
      if (second < 1) {
        yToast("录音时长太短");
      } else {
        widget.onRecordFinish.call(recordPath!, second);
      }
    } else {
      File(recordPath!).deleteSync();
    }
    chatRecordType = _ChatRecordType.Idle;
    refresh();
    removeRecordView();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: view_record(),
      onPanDown: (details) => start(details),
      onPanUpdate: (details) => update(details),
      onPanCancel: () => finish(),
      onPanEnd: (details) => finish(),
    );
  }
}
